package com.atguigu.boot.config;


import ch.qos.logback.core.db.DBHelper;
import com.atguigu.boot.bean.Car;
import com.atguigu.boot.bean.User;
import com.atguigu.boot.bean.Pet;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;


/**
 * 1、配置类里面使用@Bean标注在方法上给容器注册组件，默认也是单实例的
 * 2、配置类本身也是组件
 * 3、proxyBeanMethods：代理bean的方法
 *      Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
 *      Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
 *      组件依赖必须使用Full模式默认。其他默认是否Lite模式
 *
 *      ps：
 *          false：
 *              SpringBoot不会每次都检查@Bean是否已存在，跳过检查，启动运行速度快
 *              一般适用于：
 *                  只是简单的配置组件，不存在组件依赖情况
 *
 * 4、@Import({User.class, DBHelper.class})
 *      给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
 *
 *
 * 5、@ImportResource("classpath:beans.xml")导入Spring的配置文件，
 *
 * 6、@EnableConfigurationProperties(Car.class)
 *      1、开启Car属性配置绑定功能
 *      2、把这个Car这个组件自动注册到容器中
 *
 *      两种方式：
 *          第一种方式：
 *              在Car类上：
 *                 @Component
 *                 @ConfigurationProperties(prefix = "mycar")
 *          第二种方式：
 *              在Car类上：
 *                 @ConfigurationProperties(prefix = "mycar")
 *              在配置类上：
 *                 @EnableConfigurationProperties(Car.class)
 *
 *
 *
 */
@EnableConfigurationProperties(Car.class)
@ImportResource("classpath:beans.xml")
@Import({
        User.class,
        DBHelper.class
})   // 该注解必须标注在组件上，无论是配置类组件还是普通组件。将制定类型组件导入容器中
@Configuration(proxyBeanMethods = true) //告诉SpringBoot这是一个配置类 == xml配置文件
public class MyConfig {


    /**
     * proxyBeanMethods = true:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
     *
     * @return
     */

    @ConditionalOnBean(name = "tom22")
    @Bean
    /*
        给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。return返回的值，就是组件在容器中的实例
        <bean id="user01" class="com.atguigu.boot.bean.User">
            <property name="name"   value="张三"/>
            <property name="age"   value="18"/>
        </bean>
    */
    public User user01() {
        User user = new User("张三", 18);
        // user组件依赖pet组件 在proxyBeanMethods = true的情况下才成立
        // 循环依赖的特性，必须是单实例
        user.setPet(tomcatPet());
        return user;
    }

//    @Bean("tom22")  // 不使用方法名作为组件名，自定义组件名
    public Pet tomcatPet(){
        return new Pet("喵喵");
    }

//    @Bean
//    public CharacterEncodingFilter filter(){
//        return null;
//    }
}
